package com.yuehuanghun.framework.json;

import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.yuehuanghun.framework.json.exception.JsonParseException;
import com.yuehuanghun.framework.json.exception.JsonSerializeException;

/**
 * JSON解析处理，替换fastjson库
 * 
 * @author yadmin
 */
public class JSON {
	public static final String DEFAULT_FAIL = "\"Parse failed\"";
	private static final ObjectMapper objectMapper = new ObjectMapper();
	private static final ObjectWriter objectWriter = objectMapper.writerWithDefaultPrettyPrinter();
	static {
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }
	
	public static void toJSONString(OutputStream os, Object value) {
        try {
            objectMapper.writeValue(os, value);
        } catch (Exception e) {
            throw new JsonSerializeException(e);
        }
    }

    public static String toJSONString(Object value) {
        try {
            return objectMapper.writeValueAsString(value);
        } catch (Exception e) {
            throw new JsonSerializeException(e);
        }
    }
    
    public static String toPrettyJSONString(Object value) {
        try {
            return objectWriter.writeValueAsString(value);
        } catch (Exception e) {
            throw new JsonSerializeException(e);
        }
    }

    public static byte[] toJSONBytes(Object value) {
        try {
            return objectMapper.writeValueAsBytes(value);
        } catch (Exception e) {
            throw new JsonSerializeException(e);
        }
    }

    public static <T> T parseObject(InputStream is, Class<T> valueType) {
        try {
            return objectMapper.readValue(is, valueType);
        } catch (Exception e) {
            throw new JsonParseException(e);
        }
    }

    public static <T> T parseObject(String str, Class<T> valueType) {
        try {
            return objectMapper.readValue(str, valueType);
        } catch (Exception e) {
            throw new JsonParseException(e);
        }
    }

    public static <T> T parseObject(byte[] bytes, Class<T> valueType) {
        try {
            if (bytes == null) {
                bytes = new byte[0];
            }
            return objectMapper.readValue(bytes, 0, bytes.length, valueType);
        } catch (Exception e) {
            throw new JsonParseException(e);
        }
    }
    
    public static <T> T parseObject(String str, Type valueType) {
        try {
            return objectMapper.readValue(str, TypeFactory.defaultInstance().constructType(valueType));
        } catch (Exception e) {
            throw new JsonParseException(e);
        }
    }
    
    public static <T> List<T> parseArray(String str, Class<T> rawType) {
        try {
            Type type = new ParameterizedType() {
                
                @Override
                public Type getRawType() {
                    return ArrayList.class;
                }
                
                @Override
                public Type getOwnerType() {
                    return null ;
                }
                
                @Override
                public Type[] getActualTypeArguments() {
                    return new Class[] {rawType};
                }
            };
            return objectMapper.readValue(str, TypeFactory.defaultInstance().constructType(type));
        } catch (Exception e) {
            throw new JsonParseException(e);
        }
    }
    
    public static <T> T parseObject(String str, TypeReference<T> typeReference) {
        try {
            return objectMapper.readValue(str, typeReference);
        } catch (Exception e) {
            throw new JsonParseException(e);
        }
    }
    
    public static JSONObject parseObject(String str) {
    	if(StringUtils.isBlank(str)) {
    		return null;
    	}
        try {
            return objectMapper.readValue(str, JSONObject.class);
        } catch (Exception e) {
            throw new JsonParseException(e);
        }
    }
    
    public static Map<String, String> parseMapString(String str) {
        try {
            return objectMapper.readValue(str, new TypeReference<Map<String, String>>() {});
        } catch (Exception e) {
            throw new JsonParseException(e);
        }
    }
    
    public static Map<String, Object> parseMapObject(String str) {
        try {
            return objectMapper.readValue(str, new TypeReference<Map<String, Object>>() {});
        } catch (Exception e) {
            throw new JsonParseException(e);
        }
    }

    public static <T> T toJavaObject(Object value, Class<T> valueType) {
        return parseObject(toJSONString(value), valueType);
    }
}
